package au.com.identityconcepts.windowslive.sso.ws;

import java.io.FileInputStream;
import java.security.KeyStore;
import java.util.Iterator;
import java.util.Properties;
import java.util.TreeSet;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.TrustManagerFactory;

import org.apache.cxf.configuration.jsse.TLSClientParameters;
import org.apache.cxf.transport.http.HTTPConduit;

import com.microsoft.schemas.passport.soapservices.credentialserviceapi.v1.CredentialServiceAPISoapServer;
import com.microsoft.schemas.passport.soapservices.credentialserviceapi.v1.CredentialServiceAPISoapServerSoap;

import javax.xml.ws.BindingProvider;
import java.net.URL;
import java.net.MalformedURLException;

import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;


public class Session {	
	       	
	private static final String URI = "https://ppsacredential.service.passport.net/pksecure/PPSACredentialPK.srf";

	public org.apache.cxf.endpoint.Client client;
    public CredentialServiceAPISoapServerSoap port;
    protected Properties properties;

    protected HTTPConduit httpConduit = null;
    protected TLSClientParameters tls = null; 
    
    public boolean debug = false;
    public boolean verbose = false;
	public boolean sslDebug = false;
	   
	public String siteID = null;
	public String domain = null;
	public String domainAdmin = null;
	
	private String keyStore = null;	
	private String keyStorePassword = null;		
	private String keyStoreType = null;
	private String trustStore = null;
	private String trustStorePassword = null;
	private String trustStoreType = null;
	
	private URL WSDL = null;
	public String loginURLLive = null;
	public String loginURLExchangeLabs = null;
	public String loginURLITA = null;
	
	private static Properties system = System.getProperties();
   	
    public org.apache.cxf.endpoint.Client getClient() {
        return client;
    }

    public CredentialServiceAPISoapServerSoap getPort() {
        return port;
    }
    
    public void setClient(org.apache. cxf.endpoint.Client client) {
        this.client = client;
    }

    public void setPort(CredentialServiceAPISoapServerSoap port) {
    	this.port = port;
    }
    	
	public Session() throws Exception {			
		// Load properties
		try {
			// Retrieve the location of the WindowsLiveSSO.properties file						
			if (system.getProperty("WLIDConfigFilePath") == null)				
				system.setProperty("WLIDConfigFilePath", "c:/WindowsLiveSSO.properties");
			
			//if (this.verbose)
			//	log.debug("System property WLIDConfigFilePath is " + system.getProperty("WLIDConfigFilePath"));
			
			// Retrieve the properties stored in the WindowsLiveSSO.properties file
			properties = new Properties();
		    FileInputStream fis = new FileInputStream(system.getProperty("WLIDConfigFilePath"));
		    properties.load(fis);		
		    
			this.siteID = this.properties.getProperty("au.com.identityconcepts.windowslive.siteID");
			this.domain = this.properties.getProperty("au.com.identityconcepts.windowslive.domain");
			this.domainAdmin = this.properties.getProperty("au.com.identityconcepts.windowslive.domainAdmin");
			this.keyStore = this.properties.getProperty("au.com.identityconcepts.windowslive.keyStore");
			this.keyStorePassword = this.properties.getProperty("au.com.identityconcepts.windowslive.keyStorePassword");
			this.trustStore = this.properties.getProperty("au.com.identityconcepts.windowslive.trustStore");
			this.trustStorePassword = this.properties.getProperty("au.com.identityconcepts.windowslive.trustStorePassword");
			this.debug = Boolean.parseBoolean(this.properties.getProperty("au.com.identityconcepts.windowslive.debug"));
			this.verbose = Boolean.parseBoolean(this.properties.getProperty("au.com.identityconcepts.windowslive.verbose"));			
			this.sslDebug = Boolean.parseBoolean(this.properties.getProperty("au.com.identityconcepts.windowslive.sslDebug"));
			this.keyStoreType = this.properties.getProperty("au.com.identityconcepts.windowslive.keyStoreType");
			this.trustStoreType = this.properties.getProperty("au.com.identityconcepts.windowslive.trustStoreType");
			try {
				this.WSDL = new URL("file:" + this.properties.getProperty("au.com.identityconcepts.windowslive.WSDLPath"));
			} catch (MalformedURLException mue) {
				System.out.println("Unable to read all properties from WSDL file");
			}			
			this.loginURLLive = this.properties.getProperty("au.com.identityconcepts.windowslive.loginURLLive");
			this.loginURLExchangeLabs = this.properties.getProperty("au.com.identityconcepts.windowslive.loginURLExchangeLabs");
			this.loginURLITA = this.properties.getProperty("au.com.identityconcepts.windowslive.loginURLITA");
		} catch (Exception ex) {
			System.out.println("Current Java System Environment");
			
			// Debugging information
    		Properties pr = System.getProperties();
            TreeSet propKeys = new TreeSet(pr.keySet());  // TreeSet sorts keys
            for (Iterator it = propKeys.iterator(); it.hasNext(); ) {
                String key = (String)it.next();
                System.out.println(key + "=" + pr.get(key) + "\n");                    
            }
            
            System.out.println("Unable to read all properties from client.properties file - Session");
            ex.printStackTrace();
            
            throw ex;
		}				
					
		// Troubleshoot connectivity issues
		if (this.verbose) {	    	        		
    		Properties pr = System.getProperties();
            TreeSet propKeys = new TreeSet(pr.keySet());  // TreeSet sorts keys
            for (Iterator it = propKeys.iterator(); it.hasNext(); ) {
                String key = (String)it.next();
                System.out.println(key + "=" + pr.get(key) + "\n");                    
            }
    	}     	
		
		// Turn on SSL debugging
		if (this.sslDebug) {			
			System.setProperty("javax.net.debug","all");
			System.setProperty("java.security.debug","all");
			java.security.Security.addProvider( new com.sun.net.ssl.internal.ssl.Provider() );		
		}
				
		try 
		{
			// Build Web Service client
			CredentialServiceAPISoapServer ss = new CredentialServiceAPISoapServer(this.WSDL); 
			port = ss.getCredentialServiceAPISoapServerSoap();                 		    		    		    		
			BindingProvider bp = (BindingProvider) port; 
	        bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, URI); 	            	            	            	            
	        client = org.apache.cxf.frontend.ClientProxy.getClient(port);
		} 
		catch (Exception e) {
			System.out.println(e.toString());
			throw e;
		}
						    		    		
        // Standard SSL
		httpConduit = (HTTPConduit) client.getConduit();
		tls = new TLSClientParameters();
		tls.setSecureSocketProtocol("TLS");		    				 
		try {
			KeyStore ks = KeyStore.getInstance("PKCS12");
    		ks.load(new FileInputStream(keyStore), keyStorePassword.toCharArray());
    		KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
    		kmf.init(ks,keyStorePassword.toCharArray());
    		tls.setKeyManagers(kmf.getKeyManagers());
    		       
    		KeyStore ks2 = KeyStore.getInstance("JCEKS");
    		ks2.load(new FileInputStream(trustStore), trustStorePassword.toCharArray());
    		TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    		tmf.init(ks2);
    		tls.setTrustManagers(tmf.getTrustManagers());
		
		} catch (Exception e )  {
			System.out.println(e.toString());
			throw e;
		}		              
		httpConduit.setTlsClientParameters(tls);
		
		HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();

		  httpClientPolicy.setConnectionTimeout(36000);
		  httpClientPolicy.setAllowChunking(false);
		  httpClientPolicy.setReceiveTimeout(32000);
		  httpConduit.setClient(httpClientPolicy);
		
		this.setClient(client);
		this.setPort(port);
	}
	
	public String GetSLT(String username, int loginSeconds) 
	{
		return Marshall.GetSLT(this, username, loginSeconds);	
	}

}
